package com.learn.spring.ioc.core;

import com.learn.spring.Main;
import com.learn.spring.ioc.anno.Component;
import com.learn.spring.ioc.anno.IOCScan;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 实现IOC核心代码
 */
public class IOCCore {
    private static final String BASE_PATH = Main.class.getResource("/").getPath();

    public static void start(Class<?> primarySource) {
        start(primarySource.getAnnotation(IOCScan.class));
    }

    public static void start(IOCScan iocScan) {
        scanClass(iocScan);
    }

    /* 加载需要扫描的类 */
    private static void scanClass(IOCScan annotation) {
        String[] packages = annotation.basePackages();
        List<File> classs = new ArrayList<>();
        for(String pg : packages) {
            recursiveDir(classAbsolutePath(pg), classs);
        }

        inject(classs);
    }

    /* 初始化相关注解到容器里面去 */
    private static void inject(List<File> classs) {
        classs.stream().forEach(clazz -> {
            /* 转换class包名 */
            String classPath = classPath(clazz.getPath());
            try {
                /* 再利用java反射机制获取类 */
                Class<?> aClass1 = Class.forName(classPath);
                /* 检查是否有Component注解 */
                boolean component = aClass1.isAnnotationPresent(Component.class);
                if(component) {
                    /* 真正注入到容器 */
                    IOCContext.getInstance().registerBean(aClass1, aClass1.newInstance());
                }
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                // ignore
            }
        });
    }

    private static void recursiveDir(String filePath, List<File> classs) {
        File file = new File(filePath);
        File[] fileList = file.listFiles();
        if(fileList.length > 0) {
            for(File item : fileList) {
                if(item.isDirectory()) {
                    recursiveDir(item.getAbsolutePath(), classs);
                }else {
                    classs.add(item);
                }
            }
        }
    }

    public static String classAbsolutePath(String classPath) {
        classPath = classPath.replace(".", File.separator);
        return BASE_PATH + classPath;
    }

    public static String classPath(String classAbsolutePath) {
        return classAbsolutePath.replace(BASE_PATH, "").replace(".class", "").replace(File.separator, ".");
    }
}
